package net.hn.hnms.biz.common.jpa.utils;

import org.apache.commons.lang3.StringUtils;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;

import javax.persistence.EntityManager;
import javax.persistence.Query;
import javax.persistence.*;
import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * Author: PanSX
 * Date: 2022/8/8 15:15
 */
public class HqlUtils {
    public static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    public static <T> ResponsePage findPage(EntityManager entityManager, T obj, Pageable pageable, String defaultWhere){
           return findPage( entityManager, obj,  pageable,  defaultWhere,null);
    }
    public static <T> ResponsePage findPage(EntityManager entityManager, T obj, Pageable pageable, String defaultWhere, Sort sort) {
        List list = new ArrayList<>();
        String whereSql = "";
        Class objClass = obj.getClass();
        String s = sqlUtil(obj);
        if (!org.apache.commons.lang3.StringUtils.isEmpty(s)) {
            whereSql = " where " + s.replaceFirst("and", " ");
        }
        if (org.apache.commons.lang3.StringUtils.isNotBlank(whereSql)) {
            whereSql = whereSql + defaultWhere;
        } else {
            if (org.apache.commons.lang3.StringUtils.isNotBlank(defaultWhere)) {
                whereSql = " where " + defaultWhere.replaceFirst("and", " ");
            }
        }
        Object singleResult = entityManager.createQuery("select count(*) from  " + objClass.getName() + " T " + whereSql).getSingleResult();
        Integer count = Integer.parseInt(singleResult.toString());
        if (count > 0) {

            StringBuilder sqlList = new StringBuilder(" ");
            sqlList.append("select T from  ").append(objClass.getName()).append(" T ").append(whereSql);
            if(sort!=null){
                sqlList.append(" order by ");
                Iterator<Sort.Order> iterator = sort.iterator();
                while (iterator.hasNext()){
                    Sort.Order next = iterator.next();
                    sqlList.append( next.getProperty()).append(" ").append(next.getDirection().name());
                }
            }

            Query query = entityManager.createQuery(sqlList.toString(), objClass);

            query.setFirstResult(Integer.parseInt(pageable.getOffset() + "")).setMaxResults(pageable.getPageSize());
            list = query.getResultList();
        }
        return new ResponsePage(list,count);
    }

    private static String sqlUtil(Object o) {
        StringBuffer sb = new StringBuffer();
        Class classObj = (Class) o.getClass();
        Field[] fields = classObj.getDeclaredFields();
        for (int i = 0, len = fields.length; i < len; i++) {
            fields[i].setAccessible(true);

            //获取值
            try {
                Transient annotation = fields[i].getAnnotation(Transient.class);
                if (annotation != null) {
                    continue;
                }
                Object o1 = fields[i].get(o);
                if (o1 == null) {
                    continue;
                } else if (o1 instanceof String) {
                    if (StringUtils.isNotBlank(o1.toString())) {
                        sb.append(" and ").append(fields[i].getName()).append(" = '").append(o1).append("' ");
                    }
                } else if (o1.getClass().isPrimitive()) {//既基本数据类型
                    sb.append(" and ").append(fields[i].getName()).append(" = '").append(o1).append("' ");
                } else if (o1 instanceof Date) {
                    sb.append(" and ").append(fields[i].getName()).append(" = '").append(sdf.format(o1)).append("' ");
                } else {
                    Class s = o1.getClass();
                    try {
                        if (((Class<?>) s.getField("TYPE").get(null)).isPrimitive()) {//其封装类
                            sb.append(" and ").append(fields[i].getName()).append(" = '").append(o1).append("' ");
                        }
                    } catch (NoSuchFieldException e) {
                    }
                }

            } catch (IllegalAccessException e) {
                continue;
            }

        }
        return sb.toString();
    }
}